<?php


namespace app\common\service\utils;
use app\common\cache\member\MemberCache;
use Endroid\QrCode\Builder\Builder;
use Endroid\QrCode\Encoding\Encoding;
use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelLow;
use Endroid\QrCode\Label\Font\NotoSans;
use Endroid\QrCode\RoundBlockSizeMode\RoundBlockSizeModeMargin;

/**
 * 生成二维码
 */
class QrCodeUtils
{
    /**
     * 生成二维码
     * @Author: 易军辉
     * @DateTime:2024-08-09 11:51
     * @param $url 链接
     * @param $size 大小
     * @return string|null
     */
    public function generateQrCode($url = '',$size=100)
    {
        if (!$url){
            return  null;
        }
        $key = "generateQrCode".$size.$url;
        $info = MemberCache::get($key);
        if (empty($info)) {
            $result = Builder::create()
                ->data($url)
                ->encoding(new Encoding('UTF-8'))
                ->errorCorrectionLevel(new ErrorCorrectionLevelLow())
                ->size($size)
                ->margin(10)
                ->roundBlockSizeMode(new RoundBlockSizeModeMargin())
//            ->labelText('Scan me')
//            ->labelFont(new NotoSans(20))
                ->build();
            $info = $result->getString();
            MemberCache::set($key,$info);
            return $info;
        }else{
            return $info;
        }
    }

    /**
     * 生成二维码图片
     * @Author: 易军辉
     * @DateTime:2024-09-28 19:13
     * @param $url 生成二维码的链接
     * @param $size 大小
     * @param $code 图片保存名称
     * @param $isHttp 是否添加域名
     * @return array|string|null
     * @throws \think\Exception
     */
    public function generateQrCodeUrl($url = '',$size=100,$code='qrcode',$isHttp=true)
    {
        if (!$url){
            return  null;
        }
        $key = "generateQrCodeUrl".$size.$url.$code;
        $info = MemberCache::get($key);
        if (empty($info)) {
            $result = Builder::create()
                ->data($url)
                ->encoding(new Encoding('UTF-8'))
                ->errorCorrectionLevel(new ErrorCorrectionLevelLow())
                ->size($size)
                ->margin(10)
                ->roundBlockSizeMode(new RoundBlockSizeModeMargin())
                ->build();
            // 获取当前日期的路径部分
            $datePath = 'storage/file/' . date('Ymd') . '/';
            // 检查目录是否存在
            if (!file_exists($datePath)) {
                // 如果不存在，则尝试创建目录
                // 第二个参数是可选的模式，默认为0777，第三个参数recursive设为true可以创建多级目录
                if (!mkdir($datePath, 0755, true)) {
                    exception('无法创建目录，请联系管理员');
                }
            }
            $info = $datePath.$code.".png";
            $result->saveToFile($info);
            if($isHttp){
                $info = file_url($info);
            }
            MemberCache::set($key,$info);
            return $info;
        }else{
            return $info;
        }
    }

    /**
     * 生成海报
     * @Author: 易军辉
     * @DateTime:2024-08-09 12:01
     * @param $backgroundPath 背景图
     * @param $register_url 二维码
     * @param $activationCode 邀请码
     * @param $outputPath 保存地址
     * @return mixed
     */
    function createPoster($backgroundPath, $register_url, $activationCode, $outputPath)
    {
        $key = "createPoster".$register_url;
        $info = MemberCache::get($key);
        if (empty($info)) {
            // 加载背景图片
            // 根据文件扩展名选择正确的加载函数
            $ext = pathinfo($backgroundPath, PATHINFO_EXTENSION);

            if ($ext == 'png') {
                $background = imagecreatefrompng($backgroundPath);
            } elseif ($ext == 'jpg' || $ext == 'jpeg') {
                $background = imagecreatefromjpeg($backgroundPath);
            } elseif ($ext == 'gif') {
                $background = imagecreatefromgif($backgroundPath);
            } else {
                error_e('背景图格式有误');
            }
            // 图片宽度和高度
            $width = imagesx($background);
            $height = imagesy($background);

            // 创建二维码图片资源
            //计算宽度
            $qr_width = bcdiv($width,3);
            if($qr_width<100){
                $qr_width = 100;
            }
            $qrCodeImage = imagecreatefromstring($this->generateQrCode($register_url,$qr_width));

            // 设定二维码的位置（x, y）
            $qrCodeX = ($width - imagesx($qrCodeImage)) / 2; // 居中显示
            $qrCodeY = $height - imagesy($qrCodeImage) - 150; // 距离底部 100 像素

            // 将二维码叠加到背景图上

            imagecopy($background, $qrCodeImage, $qrCodeX, $qrCodeY, 0, 0, imagesx($qrCodeImage), imagesy($qrCodeImage));

            // 设置文本颜色
            $textColor = imagecolorallocate($background, 255, 255, 255);

            // 动态计算字体大小
            $fontSize = intval($width / 30); // 字体大小根据图片宽度动态调整
            $fontPath = root_path() . '/private/captcha/assets/zhttfs/1.ttf';
            $textBox = imagettfbbox($fontSize, 0, $fontPath, $activationCode);
            $textWidth = $textBox[2] - $textBox[0];
            $textX = ($width - $textWidth) / 2;
            $textY = $qrCodeY - 60;

            // 在图片上绘制文本
            imagettftext($background, $fontSize, 0, $textX, $textY, $textColor, $fontPath, $activationCode);


            // 将生成的图片保存到文件
            imagepng($background, $outputPath);

            // 清理内存
            imagedestroy($background);
            imagedestroy($qrCodeImage);

            MemberCache::set($key,$outputPath);
            return $outputPath;
        }else{
            return $info;
        }
    }

    /**
     * 生成商品详情海报
     * @Author: 易军辉
     * @DateTime:2024-11-21 17:05
     * @param $param
     * @return string
     */
    function createGoodsPoster($param)
    {
        // 参数解构
        $background_path = $param['background_path']; // 背景图路径
        $title = $param['title'];                     // 商品名称
        $goods_image = $param['image'];                // 商品图片URL
        $price = $param['price'];                     // 商品价格
        $original_price = $param['original_price'];   // 商品原价
        $qr_code_url = $param['qr_code_url'];         // 邀请二维码的URL
        $canvas_width = isset($param['canvas_width']) ? $param['canvas_width'] : 750;  // 画布宽度
        $canvas_height = isset($param['canvas_height']) ? $param['canvas_height'] : 1334; // 画布高度
        $member_name = $param['member_name'];//移动端名称
        $logo_url = $param['logo_url'];//logo路径

        /*************************海报名称**********************************/
        $poster_title = "";
        if(isset($param['field_value'])){
            $poster_title .=$param['field_value'];
        }
        if(isset($param['invitation_code'])){
            if($poster_title!=""){
                $poster_title .="_";
            }
            $poster_title .=$param['invitation_code'];
        }
        if(!$poster_title){
            $poster_title = 'goods_poster_' . time();
        }
        /*************************加载背景图片**********************************/
        if (file_exists($background_path)) {
            $background = imagecreatefrompng($background_path);
            $canvas_width = imagesx($background);
            $canvas_height = imagesy($background);
        }
        /*************************创建画布**********************************/
        $image = imagecreatetruecolor($canvas_width, $canvas_height);
        imagesavealpha($image, true);  // 启用透明度
        $transparent = imagecolorallocatealpha($image, 0, 0, 0, 127);  // 设置透明
        imagefill($image, 0, 0, $transparent);  // 填充透明背景

        // 设置白色背景
        $white = imagecolorallocate($image, 255, 255, 255);
        imagefill($image, 0, 0, $white);
        /*************************设置字体和颜色**********************************/
        $font_path = root_path() . '/private/captcha/assets/zhttfs/1.ttf';
        $black = imagecolorallocate($image, 33, 33, 33);
        $gray = imagecolorallocate($image, 150, 150, 150);
        $red = imagecolorallocate($image, 255, 0, 0);

        /*************************加载背景图片**********************************/
        if ($background) {
            $bg_width = imagesx($background);
            $bg_height = imagesy($background);

            // 将背景图填充到画布上
            imagecopyresampled($image, $background, 0, 0, 0, 0, $canvas_width, $canvas_height, $bg_width, $bg_height);
            imagedestroy($background);
        }
        /*************************加载logo图片**********************************/
        if($logo_url){
            $diameter = 50; // 圆形 logo 的直径
            $circularLogo = $this->createCircularLogo($logo_url, $diameter);
            if ($circularLogo) {
                // 在背景图上叠加圆形 logo
                $logoX = 40; // logo 在背景图上的 X 坐标 (可以根据需求调整)
                $logoY = 30; // logo 在背景图上的 Y 坐标 (可以根据需求调整)
                imagecopy($image, $circularLogo, $logoX, $logoY, 0, 0, $diameter, $diameter);
                imagedestroy($circularLogo);
            }
        }
        /*************************加载移动端名称**********************************/
        if($member_name){
            $font_size = 16;
            imagettftext($image, $font_size, 0, 100, 60, $black, $font_path, $member_name);
        }
        /*************************加载商品图片**********************************/
        $goods_region_w = $canvas_width - 80;  // 商品图片区域宽度
        $goods_region_h = ($canvas_height * 0.75) - 100;  // 商品图片区域高度

        if ($goods_image) {
            $productImage = @imagecreatefromjpeg($goods_image);
            if (!$productImage) {
                $productImage = @imagecreatefrompng($goods_image);
            }
            if ($productImage) {
                // 获取商品图片的宽度和高度
                $productWidth = imagesx($productImage);
                $productHeight = imagesy($productImage);

                // 计算商品图片的缩放比例，保持宽高比
                $width_ratio = $goods_region_w / $productWidth;
                $height_ratio = $goods_region_h / $productHeight;
                $scale_ratio = min($width_ratio, $height_ratio);  // 使用较小的比例，以确保图片不会被拉伸

                // 计算缩放后的商品图片宽度和高度
                $scaledWidth = $productWidth * $scale_ratio;
                $scaledHeight = $productHeight * $scale_ratio;

                // 计算商品图片的 X 和 Y 坐标，使其水平居中
                $imageX = ($canvas_width - $scaledWidth) / 2;
                $imageY = ($canvas_height * 0.1);  // 设置商品图片的 Y 坐标

                // 将商品图片绘制到画布上
                imagecopyresampled($image, $productImage, $imageX, $imageY, 0, 0, $scaledWidth, $scaledHeight, $productWidth, $productHeight);
                imagedestroy($productImage);
            }
        }
        /*************************绘制商品名称**********************************/
        $font_size = 24;
        // 设置最大宽度：画布宽度减去二维码宽度和右边的间距
        $max_width = $canvas_width - 180 - 100;//减去二维码宽度得到商品名称宽度
        // 自动换行处理
        $lines = $this->wordWrap($title, $max_width, $font_path, $font_size);
        // 绘制每一行
        $line_height = 50; // 行高
        $title_y = $canvas_height * 0.75; // 初始 Y 坐标
        foreach ($lines as $line) {
            imagettftext($image, $font_size, 0, 40, $title_y, $black, $font_path, $line);
            $title_y += $line_height; // 更新 Y 坐标
        }

        /*************************绘制商品价格**********************************/
        $price_y = $title_y;
        if($price){
            $price_text = "￥" . number_format($price, 2);
            $price_font_size = 28;
            imagettftext($image, $price_font_size, 0, 40, $price_y, $red, $font_path, $price_text);
        }

        /*************************绘制原价（划线**********************************/
        if($original_price){
            $original_price_text = "￥" . number_format($original_price, 2);
            $original_price_y = $price_y + 40;
            imagettftext($image, 20, 0, 40, $original_price_y, $gray, $font_path, $original_price_text);
            $line_length = imagettfbbox(20, 0, $font_path, $original_price_text)[2];
            imageline($image, 40, $original_price_y - 10, 40 + $line_length, $original_price_y - 10, $gray);
        }


        /*************************加载二维码**********************************/
        if($qr_code_url){
            $qrCodeImage = @imagecreatefromjpeg($qr_code_url);
            if (!$qrCodeImage) {
                $qrCodeImage = @imagecreatefrompng($qr_code_url);
            }
            if ($qrCodeImage) {
                // 缩放二维码
                $qrCodeSize = 180;
                $qrCodeX =$canvas_width - $qrCodeSize-40;
                $qrCodeY = ($canvas_height * 0.75)-40;
                imagecopyresampled($image, $qrCodeImage, $qrCodeX, $qrCodeY, 0, 0, $qrCodeSize, $qrCodeSize, imagesx($qrCodeImage), imagesy($qrCodeImage));
                imagedestroy($qrCodeImage);
            }
        }

        // 保存海报
        // 获取当前日期的路径部分
        $datePath = 'storage/file/' . date('Ymd') . '/';
        // 检查目录是否存在
        if (!file_exists($datePath)) {
            // 如果不存在，则尝试创建目录
            // 第二个参数是可选的模式，默认为0777，第三个参数recursive设为true可以创建多级目录
            if (!mkdir($datePath, 0755, true)) {
                error('无法创建目录，请联系管理员');
            }
        }

        $poster_path = $datePath.$poster_title . '.png';
        imagepng($image, $poster_path);

        // 释放资源
        imagedestroy($image);

        return $poster_path;
    }

    /**
    * 自动换行函数
    * @param string $text 文本内容
    * @param int $max_width 最大宽度
    * @param string $font_path 字体路径
    * @param int $font_size 字体大小
    * @return array 返回分割后的文本行数组
    */
    function wordWrap($text, $max_width, $font_path, $font_size)
    {
        $lines = [];
        $current_line = '';

        for ($i = 0; $i < mb_strlen($text); $i++) {
            $current_char = mb_substr($text, $i, 1); // 获取当前字符
            $test_line = $current_line . $current_char;
            $test_box = imagettfbbox($font_size, 0, $font_path, $test_line);
            $test_width = $test_box[2] - $test_box[0]; // 计算文本的宽度

            // 如果当前行加上这个字符的宽度大于最大宽度，换行
            if ($test_width <= $max_width) {
                $current_line = $test_line;
            } else {
                // 否则将当前行添加到行数组，并开始新的一行
                $lines[] = $current_line;
                $current_line = $current_char; // 当前字符开始新行
            }
        }

        // 添加最后一行
        if ($current_line) {
            $lines[] = $current_line;
        }

        return $lines;
    }
    /**
     * 将 logo 图片裁剪为圆形
     *
     * @param string $logo_url logo 图片的 URL
     * @param int $diameter 圆形的直径
     * @return resource 圆形的 logo 图像资源
     */
    function createCircularLogo($logo_url, $diameter)
    {
        // 加载 logo 图片
        $logoImage = @imagecreatefromjpeg($logo_url);
        if (!$logoImage) {
            $logoImage = @imagecreatefrompng($logo_url);
        }
        if (!$logoImage) {
            return false;
        }

        // 获取 logo 图片的宽高
        $logoWidth = imagesx($logoImage);
        $logoHeight = imagesy($logoImage);

        // 创建一个正方形的画布，尺寸为直径大小
        $circleImage = imagecreatetruecolor($diameter, $diameter);
        imagesavealpha($circleImage, true);
        $transparent = imagecolorallocatealpha($circleImage, 255, 255, 255, 127);
        imagefill($circleImage, 0, 0, $transparent);

        // 计算 logo 图片缩放比例
        $scale = min($diameter / $logoWidth, $diameter / $logoHeight);
        $newWidth = $logoWidth * $scale;
        $newHeight = $logoHeight * $scale;
        $xOffset = ($diameter - $newWidth) / 2;
        $yOffset = ($diameter - $newHeight) / 2;

        // 缩放 logo 图片并填充到圆形画布
        imagecopyresampled($circleImage, $logoImage, $xOffset, $yOffset, 0, 0, $newWidth, $newHeight, $logoWidth, $logoHeight);
        imagedestroy($logoImage);

        // 创建一个透明的圆形遮罩
        $mask = imagecreatetruecolor($diameter, $diameter);
        imagesavealpha($mask, true);
        imagefill($mask, 0, 0, $transparent);

        // 创建一个白色圆形遮罩
        $white = imagecolorallocate($mask, 255, 255, 255);
        imagefilledellipse($mask, $diameter / 2, $diameter / 2, $diameter, $diameter, $white);

        // 使用透明度合成
        imagecolortransparent($mask, $white);
        imagecopymerge($circleImage, $mask, 0, 0, 0, 0, $diameter, $diameter, 100);
        imagedestroy($mask);

        return $circleImage;
    }
}
